home *** CD-ROM | disk | FTP | other *** search
/ No Fragments Archive 12: Textmags & Docs / nf_archive_12.iso / MAGS / SOURCES / ATARI_SRC.ZIP / atari source / AHDI / TTDRIVER / ACSC / ACSC.S < prev    next >
Encoding:
Text File  |  2001-02-09  |  53.9 KB  |  2,362 lines

  1. * acsc.s
  2.     .include "version.s"
  3.  
  4. sermsg        equ    0        ; for timeout messages
  5. sahdxc        equ    0        ; simple atari hard disk command
  6. format        equ    0        ; include Format code
  7. mdsense        equ    0        ; include Mode Sense code
  8. ospool        equ    0        ; increase size of OS pool for ROM
  9. SCSI        equ    1        ; include SCSI code
  10. MC68030        equ    1        ; running on a '30
  11. VERBOSE        equ    0        ; messages out ST MFP port task time
  12. * SCDMA        equ    1        ; use DMA for SCSI transfers
  13.  
  14.   .if MC68030
  15.     .include "68030.s"
  16.   .endif ;MC68030
  17.  
  18. * default drive size (one and only one of the following)
  19. s10mb        equ    0
  20. s20mb        equ    0
  21. s11mb        equ    1
  22.  
  23. *------------------------------------------------------------------------
  24. *                                    :
  25. *    ST SASI/AHDI hard disk driver                    :
  26. *    Copyright 1985 Atari Corp.                    :
  27. *                                    :
  28. *----                                    :
  29.  
  30. * $Log:    ahdi.s,v $
  31. * Revision 1.6  86/06/13  10:56:37  dyer
  32. * Install boot-load handler code, fix some bugs and minor
  33. * misfeatures in the hard disk access code.
  34. * Revision 1.5  86/04/24  17:18:23  dyer
  35. * Add logs, fix typos, remove garbage.
  36.  
  37. *----
  38. *  9-Apr-1985 lmd    Hacked it up.  "Gee, it seems to work ..."    :
  39. * 14-Apr-1985 lmd    linked with BIOS (***FOR NOW***)        :
  40. * 20-Apr-1985 lmd    hacked for WD controller (now, wired...)    :
  41. * 24-Jun-1985 jwt    hacked for Adaptec, new kludge board        :
  42. * 01-Jul-1985 jwt    seems to work, add more formatting and more    :
  43. *             detailed error reporting            :
  44. * 22-Jul-1985 jwt    change timing of wdc/wdl at start of command,    :
  45. *             added extra move.w $8a,wdl to change A1    :
  46. * 23-Jul-1985 jwt    use a move.l instruction for all wdc/wdl write    :
  47. *             pairs since it changes A1 quickly enough that    :
  48. *             the (old) DMA chip does not incorrectly    :
  49. *             generate two chip selects            :
  50. * 26-Sep-1985 jwt v0.05    support multiple ACSI devices            :
  51. *            separate timeouts for command packet and    :
  52. *             operation                    :
  53. * 01-Oct-1985 jwt v0.06    added some AUXout serial debug messages        :
  54. *            was responding to one more drive than was there    :
  55. * 07-Oct-1985 jwt v0.07    added support for multiple partitions/drive    :
  56. * 11-Oct-1985 jwt v0.08 added delay loop after pread for completion    :
  57. *             byte                        :
  58. * 19-Oct-1985 jwt v0.09    remove format and simple commands from resident :
  59. *             part                        :
  60. *            conditional assembly for default size        :
  61. *            added count parameter to pread            :
  62. * 22-Oct-1985 jwt v0.10    make certain qdone returns d0=-1 on timeout    :
  63. *            add bits to read/write flag for:        :
  64. *             retry disable (bit 2)                :
  65. *             physical unit operation (bit 3)        :
  66. *            add pun_ptr to TOS global variables        :
  67. * 24-Oct-1985 jwt v0.11    add critical error call on errors        :
  68. * 30-Jan-1986 lmd v0.12    increase OS pool by 128 chunks for ROM release    :
  69. *             of 11/20/85                    :
  70. *          jwt    stay resident if any physical units found    :
  71. *             rather than if any GEM partitions found    :
  72. * 05-Feb-1986 jwt    call critical error handler on errors unless    :
  73. *             no-retry bit is set                :
  74. *            conditional assembly format code        :
  75. *            remove transfer only to even byte boundary    :
  76. *             restriction                    :
  77. *            remove transfer less than 128K restriction    :
  78. *            check for 0 length transfer            :
  79. * 06-Feb-1986 jwt v0.13    use register based accesses for wdc and wdl    :
  80. * 25-Mar-1986 lmd v0.14 Enforce .0005 (200th) sec delay between        :
  81. *            successive calls to _do_rw().  SCSI adapter    :
  82. *            board eats the controller's completion byte,    :
  83. *            so we have to delay for it.            :
  84. * 24-Apr-1986 lmd v1.1    Hack pool_install code to increase pool for    :
  85. *            other ROM releases of the system.        :
  86. * 24-Apr-1986 lmd v1.4    Print nasty messages for old disk-based and    :
  87. *            unauthorized ROM-based systems.            :
  88. * 23-Jun-1987 lmd v1.5  Fix date-check in nasty-OS-message code; wrong    :
  89. *            offset into the OS header (now $1e).        :
  90. *                                    :
  91. * 06-Nov-1987 akp v1.7    Added procedure findpackages and call to it.    :
  92. * 10-Nov-1987 akp    Changed source to MADMAC format.        :
  93. *            Removed format flag from top of file.        :
  94. * 24-Nov-1987 akp    Really made v1.7 work.                :
  95. * 19-Feb-1987 ml    Added format and mode sense code for use in     :
  96. *            HDX  (It's conditional, code will only be    :
  97. *            included for ahdi.prg, and not shdriver.sys).    :
  98. * 23-Feb-1989 jwt    hack in some SCSI 5380 code
  99. *------------------------------------------------------------------------
  100.  
  101. etv_critic    equ    $404        ; critical error handoff vector
  102. phystop        equ    $42e        ; physical top of memory
  103. flock        equ    $43e        ; FIFO lock variable
  104. _bootdev    equ    $446        ; default boot device
  105. _hz_200        equ    $4ba        ; system 200hz timer
  106. hdv_init    equ    $46a        ; hdv_init()
  107. hdv_bpb        equ    $472        ; hdv_bpb(dev)
  108. hdv_rw        equ    $476        ; hdv_rw(rw, buf, count, recno, dev)
  109. hdv_boot    equ    $47a        ; hdv_boot()
  110. hdv_mediach    equ    $47e        ; hdv_mediach(dev)
  111. _drvbits    equ    $4c2        ; block device bitVector
  112. _dskbufp    equ    $4c6        ; pointer to common disk buffer
  113. pun_ptr        equ    $516        ; pointer to physical unit table
  114.  
  115. maxunits    equ    16        ; maximum number of units
  116. nretries    equ    3        ; #retries-1
  117.  
  118. MAXSECTORS    equ    254        ; maximum number of sectors at one gulp
  119.  
  120. EWRITF        equ    -10        ; GEMDOS error codes
  121. EREADF        equ    -11
  122. CRITRETRY    equ    $00010000    ; "retry" return code
  123.  
  124.  .if ospool
  125. _sysbase    = $4f2            ; -> base of OS
  126. numchunks    = 128            ; #chunks to add to pool
  127. chunksiz    = 66            ; #bytes/chunk
  128. chunkno        = 4            ; chunk# (4 16-byte chunks)
  129.  .endif
  130.  
  131. * ---------------- Installer ----------------
  132.     .globl    i_sasi
  133. i_sasi:    bra.w    i_sasi1            ; GEMDOS entry-point
  134.     st    bootloaded        ; boot entry-point, set flag
  135.     move.l    a2,baseaddr        ; install base address
  136.     bra    i_sasi1            ; (continue with normal initialization)
  137.  
  138. bootloaded:    dc.w    0        ; nonzero if loaded from boot sector
  139. baseaddr:    dc.l    0        ; -> base addr of .PRG file
  140.  
  141.     dc.b    '@(#)acsc.s '
  142.   .if !SCDMA
  143.     dc.b    '(ND) '
  144.   .endif ;SCDMA
  145.     dc.b    ' '
  146.     VERSION
  147.     dc.b    $0d,$0a,0,$1A
  148.     .even
  149.  
  150. * page 
  151. * ---------------- Front End ----------------
  152.  
  153.  
  154. *+
  155. * LONG hbpb(dev) - return ptr to BPB (or NULL)
  156. *
  157. * Passed:    dev    4(sp).W
  158. *
  159. *-
  160. hbpb:
  161.     move.w    4(sp),d0        ; d0 = devno
  162.     clr    d1            ; d1 = 0, physical op not possible
  163.     move.l    o_bpb,a0        ; a0 -> pass-through vector
  164.     lea    _sasi_bpb(pc),a1    ; a1 -> our handler
  165.     bra    check_dev        ; do it
  166.  
  167.  
  168.  
  169. *+
  170. * LONG hrw(rw, buf, count, recno, dev)
  171. *
  172. * Passed:    dev    $e(sp).W
  173. *        recno    $c(sp).W
  174. *        count    $a(sp).W
  175. *        buf    6(sp).L
  176. *        rw    4(sp).W
  177. *
  178. *-
  179. hrw:
  180.     move.w    $e(sp),d0        ; d0 = devno
  181.     move.w    4(sp),d1        ; d1 includes physical device flag
  182.     move.l    o_rw,a0            ; a0 -> pass-through vector
  183.     lea    _sasi_rw(pc),a1        ; a1 -> our handler
  184.     bra    check_dev        ; do it
  185.  
  186.  
  187.  
  188. *+
  189. * LONG hmediach(dev)
  190. *
  191. * Passed:    dev    4(sp).W
  192. *
  193. *-
  194. hmediach:
  195.     move.w    4(sp),d0        ; d0 = devno
  196.     clr    d1            ; physical operation not possible
  197.     move.l    o_mediach,a0        ; a0 -> pass-through vector
  198.     lea    _sasi_mediach(pc),a1    ; a1 -> our handler
  199.  
  200.  
  201. *+
  202. * check_dev - use handler, or pass vector through
  203. *
  204. * Passed:    d0.w = device#
  205. *        d1, bit 3  1=physical operation
  206. *        a0 ->  old handler
  207. *        a1 ->  new handler
  208. *        a5 ->  $0000 (zero-page ptr)
  209. *
  210. * Jumps-to:    (a1) if dev in range for this handler
  211. *        (a0) otherwise
  212. *
  213. *-
  214. check_dev:
  215.     btst    #3,d1            ; is this a physical unit operation?
  216.     beq    chkd_a
  217.  
  218. ;    subq    #2,d0            ; lowest device is C
  219. ;    bmi    chkd_f            ; not one of ours
  220.  
  221. ;    cmp    puns,d0
  222. ;    bge    chkd_f
  223.     bra    chkd_s
  224.  
  225. chkd_a:    lea    pun,a2            ; pointer to pun map
  226.     tst.b    0(a2,d0.w)        ; must be positive for a real unit
  227.     bmi    chkd_f
  228. chkd_s:    move.l    a1,a0            ; yes -- follow success vector
  229. chkd_f:    jmp    (a0)            ; do it
  230.  
  231.  
  232.  
  233. * page 
  234. * ---------------- Medium level driver ----------------
  235.  
  236. *+
  237. * _sasi_init - initialize SASI dev
  238. * Passed:    nothing
  239. * Returns:    d0 < 0: error
  240. *        d0 ==0: success
  241. *-
  242.     .globl    _sasi_init
  243. _sasi_init:
  244.     clr.l    d0
  245.     rts
  246.  
  247. *+
  248. * _sasi_bpb - return BPB for hard drive
  249. * Synopsis:    LONG _sasi_bpb(dev)
  250. *        WORD dev;
  251. *
  252. * Returns:    NULL, or a pointer to the BPB buffer
  253. *
  254. *-
  255.     .globl    _sasi_bpb
  256. _sasi_bpb:
  257.     move.w    4(sp),d0        ; get device number
  258.     mulu.w    #BPBLEN,d0
  259.     add.l    #bpbs,d0
  260.     rts
  261.  
  262. * page 
  263. *+
  264. * _ahdi_rw - read/write hard sectors
  265. *     aka _sasi_rw for historical reasons
  266. *
  267. * Synopsis:    _ahdi_rw(rw, buf, count, recno, dev)
  268. *
  269. * Passed:    dev    $e(sp).W
  270. *        recno    $c(sp).W
  271. *        count    $a(sp).W
  272. *        buf    6(sp).L
  273. *        rw    4(sp).W        ; non-zero -> write
  274. *
  275. *-
  276.  
  277. * stack frame offsets
  278. xrw    equ    8
  279. xbuf    equ    10
  280. xcount    equ    14
  281. xrecno    equ    16
  282. xdev    equ    18
  283. xlrecno    equ    20
  284.  
  285.     .globl    _sasi_rw
  286.     .globl    _ahdi_rw
  287. _sasi_rw:
  288. _ahdi_rw:
  289.     link    a6,#0            ; create a frame pointer
  290.  
  291. ahrw1:    move.w    xcount(a6),d2        ; is there anything to be done?
  292.     beq    ahrw6            ; no, so done with no errors
  293.  
  294.   .if SCSI
  295.     move.w    xdev(a6),d1        ; get the device number
  296.     move.w    xrw(a6),d3        ; see if this is to be a phys op
  297.     btst    #3,d3
  298.     beq.s    .1            ; no, logical operation
  299.     cmpi.w    #9,d1            ; is it bigger than largest ACSI unit?
  300.     ble.s    ahrw11            ; no, so must be phys ACSI
  301.     bra    scrw
  302.  
  303. .1:    lea    pun,a2
  304.     move.b    0(a2,d1.w),d0        ; get logical unit flags
  305.     btst    #6,d0            ; is the SCSI bit set?
  306.     bne    scrw            ; yes, so a SCSI operation
  307.   .endif ;SCSI
  308.     
  309. ahrw11:    move.l    xbuf(a6),d1        ; if all goes well, this is our buffer
  310.  
  311.     cmpi.w    #MAXSECTORS,d2        ; more than one DMAfull?
  312.     ble    ahrw2
  313.     move.w    #MAXSECTORS,d2        ; yes, so only do this many this time
  314.  
  315. ahrw2:    btst    #0,xbuf+3(a6)        ; an odd boundary?
  316.     beq    ahrw4            ; no, so do normally
  317.  
  318.     cmpi.w    #2,d2            ; can only do 2 at a time tops this way
  319.     ble    ahrw3
  320.     move.w    #2,d2
  321.  
  322. ahrw3:    move.l    _dskbufp,d1        ; use the bios buffer for this transfer
  323.  
  324.     btst    #0,xrw+1(a6)        ; is this a write?
  325.     beq    ahrw4            ; no, so go fill buffer from disk
  326.  
  327.     movea.l    d1,a1            ; dest
  328.     movea.l    xbuf(a6),a2        ; source
  329.     bsr    smove            ; move d2 sectors from a2 to a1
  330.  
  331. ahrw4:    move.w    d2,-(sp)        ; preserve count this time
  332.  
  333.     move.w    xdev(a6),-(sp)
  334.     move.w    xrecno(a6),-(sp)
  335.     move.w    d2,-(sp)        ; count
  336.     move.l    d1,-(sp)        ; buffer
  337.     move.w    xrw(a6),-(sp)
  338.     bsr    _do_rw
  339.     adda.w    #12,sp
  340.  
  341.     move.w    (sp)+,d2        ; restore count for this op
  342.  
  343.     tst.l    d0            ; any errors there?
  344.     bne    ahrw7            ; yes, so give up
  345.  
  346.     btst    #0,xbuf+3(a6)        ; if odd boundary
  347.     beq    ahrw5
  348.     btst    #0,xrw+1(a6)        ; and a read
  349.     bne    ahrw5
  350.  
  351.     movea.l    xbuf(a6),a1        ; we must move dskbuf to desired dest
  352.     movea.l    _dskbufp,a2
  353.     bsr    smove
  354.  
  355. ahrw5:    move.w    d2,d0            ; number we did
  356.     ext.l    d0
  357.     asl.l    #8,d0            ; *512
  358.     asl.l    #1,d0
  359.     add.l    d0,xbuf(a6)        ; buf += (sectors_done * sector size)
  360.     add.w    d2,xrecno(a6)
  361.     sub.w    d2,xcount(a6)
  362.     bne    ahrw1
  363.  
  364. ahrw6:    clr.l    d0        ; got here with no errors!
  365. ahrw7:
  366.   .if MC68030
  367.     move.l    d0,-(sp)    ; save the status
  368.     move    sr,-(sp)
  369.     ori    #$700,sr    ; no interrupts right now please
  370.  
  371.     movecacrd0
  372.  
  373.     btst    #7,xrw(a6)    ; are we supposed to leave I cache alone?
  374.     bne.s    .91        ; yes
  375.  
  376.     ori    #$8,d0        ; dump the I cache
  377.  
  378. .91:    btst    #6,xrw(a6)    ; are we supposed to leave D cache alone?
  379.     bne.s    .92        ; yes
  380.  
  381.     ori    #$800,d0    ; dump the D cache
  382.  
  383. .92:    moved0cacr
  384.     move    (sp)+,sr    ; restore interrupt state
  385.  
  386.     move.l    (sp)+,d0    ; restore the return value
  387.   .endif ;MC68030
  388.     unlk    a6
  389.     rts
  390.  
  391. *+
  392. * smove -- move d2.w sectors from a2 to a1
  393. *    d2 is known to be either 1 or 2
  394. *-
  395.  
  396. smove:    move.w    d2,d0
  397.     asl.w    #8,d0
  398.     asl.w    #1,d0
  399.     subq.w    #1,d0            ; dbra likes one less
  400. smove1:    move.b    (a2)+,(a1)+
  401.     dbra    d0,smove1
  402.     rts
  403.  
  404. * page 
  405. *+
  406. * scrw -- a SCSI disk rwabs()
  407. *-
  408.   .if SCSI
  409. REGBASE    equ    1    ; most are on odd part of data bus
  410. REGSTEP    equ    2    ; most registers are on word boundaries
  411.  
  412. ; 68901 MFP definitions
  413.  
  414. MFP    equ    $FFFFFA01
  415.  
  416. ;GPIP    equ    MFP+$00
  417. AER    equ    MFP+$02
  418. DDR    equ    MFP+$04
  419. IERA    equ    MFP+$06
  420. IERB    equ    MFP+$08
  421. IPRA    equ    MFP+$0A
  422. IPRB    equ    MFP+$0C
  423. ISRA    equ    MFP+$0E
  424. ISRB    equ    MFP+$10
  425. IMRA    equ    MFP+$12
  426. IMRB    equ    MFP+$14
  427. VR    equ    MFP+$16
  428. TACR    equ    MFP+$18
  429. TBCR    equ    MFP+$1A
  430. TCDCR    equ    MFP+$1C
  431. TADR    equ    MFP+$1E
  432. TBDR    equ    MFP+$20
  433. TCDR    equ    MFP+$22
  434. TDDR    equ    MFP+$24
  435. SCR    equ    MFP+$26
  436. UCR    equ    MFP+$28
  437. RSR    equ    MFP+$2A
  438. TSR    equ    MFP+$2C
  439. UDR    equ    MFP+$2E
  440.  
  441. MFP2    equ    $FFFFFA81
  442. GPIP2    equ    MFP2+$00
  443. AER2    equ    MFP2+$02
  444. DDR2    equ    MFP2+$04
  445. IERA2    equ    MFP2+$06
  446. IERB2    equ    MFP2+$08
  447. IPRA2    equ    MFP2+$0A
  448. IPRB2    equ    MFP2+$0C
  449. ISRA2    equ    MFP2+$0E
  450. ISRB2    equ    MFP2+$10
  451. IMRA2    equ    MFP2+$12
  452. IMRB2    equ    MFP2+$14
  453. VR2    equ    MFP2+$16
  454. TACR2    equ    MFP2+$18
  455. TBCR2    equ    MFP2+$1A
  456. TCDCR2    equ    MFP2+$1C
  457. TADR2    equ    MFP2+$1E
  458. TBDR2    equ    MFP2+$20
  459. TCDR2    equ    MFP2+$22
  460. TDDR2    equ    MFP2+$24
  461. SCR2    equ    MFP2+$26
  462. UCR2    equ    MFP2+$28
  463. RSR2    equ    MFP2+$2A
  464. TSR2    equ    MFP2+$2C
  465. UDR2    equ    MFP2+$2E
  466.     
  467. ; GPIP2 BIT ASSIGNMENTS
  468. GPIP2SCSI    equ    7    ; SCSI xIRQ
  469. GPIP2RTC    equ    6    ; RTC IRQ
  470. GPIP25        equ    5    ; 
  471. GPIP2CHGL    equ    4    ; ChangeLine
  472. GPIP2RI        equ    3    ; Ring Indicator (SCC Port B)
  473. GPIP2DBE    equ    2    ; DMA Bus Error
  474. LED1        equ    1    ; debug LED
  475. LED0        equ    0    ; debug LED
  476.  
  477. ; SCSI Interface (NCR 5380) for READ operations
  478. bSCSI    equ    $FFFF8780+REGBASE
  479. SCSIDB    equ    bSCSI+($00*REGSTEP)    ; current SCSI data bus
  480. SCSIICR    equ    bSCSI+($01*REGSTEP)    ; initiator command register
  481. SCSIMR    equ    bSCSI+($02*REGSTEP)    ; mode register
  482. SCSITCR    equ    bSCSI+($03*REGSTEP)    ; target command register
  483. SCSICR    equ    bSCSI+($04*REGSTEP)    ; current SCSI control register
  484. SCSIDSR    equ    bSCSI+($05*REGSTEP)    ; DMA status register
  485. SCSIIDR    equ    bSCSI+($06*REGSTEP)    ; input data register
  486. SCSIREI    equ    bSCSI+($07*REGSTEP)    ; reset error / interrupt
  487.  
  488. ; SCSI Interface (NCR 5380) for WRITE operations
  489. SCSIODR    equ    bSCSI+($00*REGSTEP)    ; output data register
  490. ;SCSIICR    bSCSI+($01*REGSTEP)    ; initiator command register
  491. ;SCSIMR        bSCSI+($02*REGSTEP)    ; mode register
  492. ;SCSITCR    bSCSI+($03*REGSTEP)    ; target command register
  493. SCSIISR    equ    bSCSI+($04*REGSTEP)    ; ID select register
  494. SCSIDS    equ    bSCSI+($05*REGSTEP)    ; start DMA send
  495. SCSIDTR    equ    bSCSI+($06*REGSTEP)    ; start DMS target receive
  496. SCSIDIR    equ    bSCSI+($07*REGSTEP)    ; start DMA initiator receive
  497.  
  498. ; SCSI DMA Controller
  499. bSDMAPTR    equ    $FFFF8701
  500. bSDMACNT    equ    $FFFF8709
  501. SDMARES    equ    $FFFF8710
  502. SDMACTL    equ    $FFFF8714    ; WORD
  503.  
  504. DMAOUT    equ    01
  505. DMAIN    equ    00
  506. DMAENA    equ    02
  507. DMADIS    equ    00
  508.  
  509. SCSIID    equ    6        ; our (host) SCSI ID
  510.  
  511.   .macro w4req
  512. .1\~:    btst    #5,SCSICR        ; waiting for REQ to come
  513.     beq.s    .1\~
  514.   .endm
  515.  
  516.   .macro doack
  517.     ori.b    #$11,SCSIICR        ; assert ACK (and data bus)
  518. .1\~:    btst    #5,SCSICR        ; wait for REQ to go away
  519.     bne.s    .1\~
  520.     andi.b    #$ef,SCSIICR        ; clear ACK
  521.   .endm
  522.  
  523.   .macro hshake    xbyte
  524.     w4req
  525.     move.b    \xbyte,SCSIDB        ; write a byte out to data bus
  526.     doack
  527.   .endm
  528.  
  529.   .macro w4irq
  530. .1\~:    btst    #5,GPIP
  531.     bne.s    .1\~
  532.   .endm
  533.  
  534.  
  535. scrw:    move.w    _retries,retrycnt    ; setup retry counter
  536. scrw0:    move.w    xdev(a6),d0    ; get the unit number
  537.     btst    #3,xrw+1(a6)    ; is this a physical operation?
  538.     beq.s    .0        ; no, so go get unit from pun
  539.     subi.w    #10,d0        ; subtract number of floppy&ACSI units
  540.     bra.s    .1        ; and use that as the unit number
  541.  
  542. .0:    lea    pun,a2
  543.     move.b    (a2,d0.w),d0    ; get the physical unit number
  544.     andi.w    #3,d0        ; strip off the flags
  545.  
  546. .1:    move.w    d0,-(sp)
  547.     bsr    selSCSI        ; select the SCSI device
  548.     addq    #2,sp
  549.  
  550.   .if SCDMA
  551.     move.l    xbuf(a6),d0    ; set the DMA source/destination
  552.     move.b    d0,bSDMAPTR+6
  553.     lsr.l    #8,d0
  554.     move.b    d0,bSDMAPTR+4
  555.     lsr.l    #8,d0
  556.     move.b    d0,bSDMAPTR+2
  557.     lsr.l    #8,d0
  558.     move.b    d0,bSDMAPTR
  559.  
  560. ; set up the size of the transfer (in bytes, assume each sector = $0200 bytes)
  561.     clr.l    d0
  562.     move.w    xcount(a6),d0    ; get the count of sectors
  563.     move.b    #0,bSDMACNT+6    ; lsb of byte cnt always 0
  564.     lsl.l    #1,d0        ; *$200/$100
  565.     move.b    d0,bSDMACNT+4
  566.     lsr.l    #8,d0
  567.     move.b    d0,bSDMACNT+2
  568.     lsr.l    #8,d0
  569.     move.b    d0,bSDMACNT
  570.   .endif ;SCDMA
  571.  
  572.     clr.l    d1
  573.     move.w    xrecno(a6),d1    ; get the record number
  574.     cmpi.w    #-1,d1        ; is recno==-1
  575.     bne.s    .11        ; if not, then use it
  576.     move.l    xlrecno(a6),d1    ; if so, then it implies the long form
  577. .11:    btst    #3,xrw+1(a6)    ; is it a physical operation?
  578.     bne.s    .15        ; yes, so don't change record number
  579.     move.w    xdev(a6),d2    ; get the logical unit number again
  580.     lsl.w    #2,d2        ; make it a long word index
  581.     lea    start,a2    ; and a pointer to the offset table
  582.     add.l    (a2,d2.w),d1    ; add the starting offset to specified record
  583. .15:
  584.   .if VERBOSE
  585.     movem.l    d0-d3/a0-a3,-(sp)
  586.     move.l    d1,-(sp)
  587.     bsr    crlf
  588.     move.b    #'R',d0
  589.     btst    #0,xrw+1(a6)
  590.     beq.s    .100
  591.     move.b    #'W',d0
  592. .100:    bsr    putc
  593.     move.w    retrycnt,d0
  594.     bsr    putnib
  595.     move.b    #':',d0
  596.     bsr    putc
  597.     move.w    xcount(a6),d0
  598.     bsr    putwor
  599.     move.b    #'#',d0
  600.     bsr    putc
  601.     move.l    (sp),d0
  602.     bsr    putlon
  603.     move.b    #'@',d0
  604.     bsr    putc
  605.     move.l    xbuf(a6),d0
  606.     bsr    putlon
  607.     move.l    (sp)+,d1
  608.     movem.l    (sp)+,d0-d3/a0-a3
  609.   .endif ;VERBOSE
  610.     move.b    #$28,d0        ; SCSI read extended command
  611.     btst    #0,xrw+1(a6)    ; read or write?
  612.     beq.s    .16
  613.     move.b    #$2A,d0        ; SCSI write extended command
  614. .16:    move.b    #2,SCSITCR    ; assert C/D
  615.     move.b    #1,SCSIICR    ; assert data bus
  616.     hshake    d0        ; write the command     -- 00 --
  617.     hshake    #0        ;                       -- 01 --
  618.     move.l    d1,d0        ; get the long block number
  619.     rol.l    #8,d0        ; send 4 bytes of block number
  620.     hshake    d0        ;                       -- 02 --
  621.     rol.l    #8,d0
  622.     hshake    d0        ;                       -- 03 --
  623.     rol.l    #8,d0
  624.     hshake    d0        ;                       -- 04 --
  625.     rol.l    #8,d0
  626.     hshake    d0        ;                       -- 05 --
  627.     hshake    #0        ; reserved byte         -- 06 --
  628.     move.w    xcount(a6),d0    ; word of count
  629.     rol.w    #8,d0
  630.     hshake    d0        ;                       -- 07 --
  631.     rol.w    #8,d0
  632.     hshake    d0        ;                       -- 08 --
  633.   .if 0
  634.     bra    .18        ; go send the control byte
  635.  
  636. ; send the SCSI command to the device
  637. .0:    move.b    #$08,d0        ; SCSI read command
  638.     btst    #0,xrw+1(a6)    ; only use lsb here, others reserved
  639.     beq.s    .1
  640.     move.b    #$0a,d0        ; SCSI write command
  641. .1:    move.b    #2,bSCSI+(3*REGSTEP)    ; assert c/d
  642.     move.b    #1,bSCSI+(1*REGSTEP)    ; assert data bus
  643.     hshake    d0        ; write the command     -- 00 --
  644.     hshake    #0        ; unfortunately rwabs only uses word block num
  645.     move.w    xrecno(a6),d0    ; get the specified block number
  646.     lsr.w    #8,d0
  647.     hshake    d0        ;                       -- 02 --
  648.     move.w    xrecno(a6),d0
  649.     hshake    d0        ;                       -- 03 --
  650.     move.w    xcount(a6),d0
  651.     hshake    d0        ;                       -- 04 --
  652.   .endif ;0
  653. .18:    hshake    #0        ; control byte always 0 -- 05 -- or -- 09 --
  654.  
  655.     btst    #0,xrw+1(a6)    ; only use lsb here, others reserved
  656.     beq.s    .25
  657.  
  658. ; write
  659.   .if SCDMA
  660.     move.b    #0,SCSITCR        ; set data out phase
  661.     move.b    SCSIREI,d0        ; clear potential interrupt
  662.     move.b    #2,SCSIMR        ; enable DMA mode
  663.     move.b    #0,SCSIDS        ; start the DMA send
  664.     move.w    #DMAOUT,SDMACTL        ; set the DMAC direction
  665.     move.w    #DMAOUT+DMAENA,SDMACTL    ; turn on DMAC
  666.     bra.s    .26
  667.   .else ;SCDMA
  668.     movea.l    #bSCSI,a0        ; pointer to the 5380
  669.     move.b    #0,3*REGSTEP(a0)    ; set data out phase
  670.     move.b    7*REGSTEP(a0),d0    ; clear potential interrupt
  671.     movea.l    xbuf(a6),a1        ; buffer pointer
  672.  
  673. .22:    btst    #5,4*REGSTEP(a0)    ; wait for REQ
  674.     beq.s    .22
  675.     btst    #3,5*REGSTEP(a0)    ; still in right phase
  676.     beq.s    .3            ; no, end of data out phase
  677.     move.b    (a1)+,(a0)        ; write the data byte
  678.  
  679.     bset    #4,1*REGSTEP(a0)    ; assert ACK
  680.  
  681. .23:    btst    #5,4*REGSTEP(a0)    ; wait for REQ to go away
  682.     bne.s    .23
  683.  
  684.     bclr    #4,1*REGSTEP(a0)    ; clear ACK
  685.     bra.s    .22
  686.   .endif ;SCDMA
  687.  
  688. ; read
  689. .25:
  690.   .if SCDMA
  691.     move.b    #0,SCSIICR        ; deassert the data bus
  692.     move.b    #1,SCSITCR        ; set data in phase
  693.     move.b    SCSIREI,d0        ; clear potential interrupt
  694.     move.b    #2,SCSIMR        ; enable DMA mode
  695.     move.b    #0,SCSIDIR        ; start the DMA receive
  696.     move.w    #DMAIN,SDMACTL        ; set the DMAC direction
  697.     move.w    #DMAIN+DMAENA,SDMACTL    ; turn on DMAC
  698.  
  699. .26:    btst    #GPIP2SCSI,GPIP2    ; wait for 5380 to interrupt
  700.     bne.s    .261            ; active HIGH
  701.     btst    #5,GPIP2        ; or for DMAC to interrupt
  702.     bne.s    .26            ; active LOW
  703.     move.w    SDMACTL,d0        ; get the DMA status
  704.     andi.l    #$80,d0            ; ignore countout ints
  705.     beq.s    .26
  706.     neg.l    d0
  707.     move.l    d0,-(sp)
  708.     bsr    resetSCSI
  709.     move.l    (sp)+,d0
  710.     bra    .99
  711.  
  712. .261:    move.b    SCSIREI,d0        ; clear potential interrupt
  713.  
  714. ; disable DMA
  715.     move.w    #DMADIS,SDMACTL
  716.  
  717.     move.b    #0,SCSIMR        ; disable DMA mode
  718.     move.b    #0,SCSIICR        ; make sure data bus is not asserted
  719.   .else ;SCDMA
  720.     movea.l    #bSCSI,a0        ; pointer to the 5380
  721.     move.b    #1,3*REGSTEP(a0)    ; set data in phase
  722.     move.b    7*REGSTEP(a0),d0    ; clear potential interrupt
  723.     movea.l    xbuf(a6),a1        ; buffer pointer
  724.  
  725. .27:    btst    #5,4*REGSTEP(a0)    ; wait for REQ
  726.     beq.s    .27
  727.     btst    #3,5*REGSTEP(a0)    ; still in right phase
  728.     beq.s    .3            ; no, end of data in phase
  729.     move.b    (a0),(a1)+        ; read the data byte
  730.  
  731.     bset    #4,1*REGSTEP(a0)    ; assert ACK
  732.  
  733. .28:    btst    #5,4*REGSTEP(a0)    ; wait for REQ to go away
  734.     bne.s    .28
  735.  
  736.     bclr    #4,1*REGSTEP(a0)    ; clear ACK
  737.     bra.s    .27
  738.  
  739.   .endif ;SCDMA
  740.  
  741. .3:    move.b    #3,SCSITCR        ; status in phase
  742.     move.b    SCSIREI,d0        ; clear potential interrupt
  743.  
  744.     w4req                ; wait for status byte
  745.     clr.w    d0
  746.     move.b    bSCSI,d0
  747.     move.w    d0,-(sp)
  748.     doack
  749.  
  750.     w4req
  751.     move.b    bSCSI,d0        ; get and ignore message byte
  752.     doack
  753.  
  754.   .if VERBOSE
  755.     move.b    #'^',d0
  756.     bsr    putc
  757.     move.w    (sp),d0
  758.     bsr    putbyt
  759.   .endif ;VERBOSE
  760.  
  761.     btst    #0,xrw+1(a6)    ; only use lsb here, others reserved
  762.     bne.s    .9        ; if this was a write, we are done
  763.  
  764.     move.b    bSDMAPTR+6,d0    ; see if this was an odd transfer
  765.  
  766.     andi.w    #3,d0
  767.     beq.s    .9        ; no, nice and even (and easy)
  768.  
  769.     move.b    bSDMAPTR+0,d0
  770.     lsl.l    #8,d0
  771.     move.b    bSDMAPTR+2,d0
  772.     lsl.l    #8,d0
  773.     move.b    bSDMAPTR+4,d0
  774.     lsl.l    #8,d0
  775.     move.b    bSDMAPTR+6,d0
  776.     move.l    d0,d1
  777.     andi.w    #3,d0
  778.  
  779.     andi.w    #$FFFF-3,d1    ; where does the data go?
  780.     movea.l    d1,a0
  781.     move.l    SDMARES,d1    ; get the residue
  782.     subq.w    #1,d0        ; dbra likes one less than count
  783. .8:    rol.l    #8,d1
  784.     move.b    d1,(a0)+
  785.     dbra    d0,.8
  786. .9:    clr.l    d0
  787.  
  788.     move.w    (sp)+,d0    ; recall the status byte
  789.     beq.s    .99
  790.     neg.l    d0        ; errors are negative numbers
  791.     subq.w    #1,retrycnt    ; drop retry count and retry
  792.     bpl    scrw0        ; if there are still chances to win
  793.  
  794. .99:    bra    ahrw7
  795.  
  796. *+
  797. * VOID resetSCSI();
  798. *-
  799.  
  800. resetSCSI:
  801.     move.b    #$80,SCSIICR    ; assert RST
  802.     movea.l    #_hz_200,a0
  803.     move.l    (a0),d0
  804.     addi.l    #51,d0        ; wait (at least) 250 mS
  805. .0:    cmp.l    (a0),d0
  806.     bne.s    .0
  807.     move.b    #$00,SCSIICR
  808.     move.l    (a0),d0
  809.     addi.l    #201,d0        ; wait (at least) 1000 mS
  810. .1:    cmp.l    (a0),d0
  811.     bne.s    .1
  812.     rts
  813.  
  814. *+
  815. * BOOLEAN selSCSI(SCSIUnit) WORD SCSIUnit;
  816. *-
  817.  
  818. selSCSI:
  819. .0:    btst    #6,SCSICR        ; not STILL busy from last time?
  820.     bne.s    .0
  821.  
  822.     move.b    #0,SCSITCR        ; data out phase
  823.     move.b    #0,SCSIISR        ; no interrupt from selection
  824.     move.b    #$0c,SCSIICR        ; assert BSY and SEL
  825. ; set dest SCSI IDs
  826.     clr.w    d0
  827.     move.w    4(sp),d1        ; get the SCSI unit desired
  828.     bset    d1,d0            ; set the appropriate bit
  829.     move.b    d0,SCSIODR        ; (real code would set ours too)
  830.  
  831.     move.b    #$0d,SCSIICR        ; assert BUSY, SEL and data bus
  832.  
  833.     andi.b    #$FE,SCSIMR        ; clear arbitrate bit
  834.     andi.b    #$F7,SCSIICR        ; clear BUSY
  835.     nop
  836.     nop
  837.  
  838. .1:    btst    #6,SCSICR        ; wait for bus to be busy
  839.     beq    .1
  840.  
  841.     move.b    #$0,SCSIICR        ; clear SEL and data bus assertion
  842.     clr.w    d0            ; note lack of SCSI device timeout
  843.     rts
  844.  
  845.   .endif ;SCSI
  846.  
  847.   .if VERBOSE
  848. ;
  849. ;    putlon - put d0.l as 8 hex digits
  850. ;    putwor - put d0.w as 4 hex digits
  851. ;    putbyt - put d0.b as 2 hex digits
  852. ;    putnib - put 4 lsbs as a hex digit
  853.  
  854. putlon:    move.l    d0,-(sp)
  855.     swap    d0
  856.     bsr    putwor
  857.     move.l    (sp)+,d0
  858. putwor:    move    d0,-(sp)
  859.     asr    #8,d0
  860.     bsr    putbyt
  861.     move    (sp)+,d0
  862. putbyt:    move    d0,-(sp)
  863.     asr    #4,d0
  864.     bsr    putnib
  865.     move    (sp)+,d0
  866. putnib:    andi.b    #$0f,d0
  867.     addi.b    #'0',d0
  868.     cmpi.b    #'9',d0
  869.     ble    putb2
  870.     addi.b    #7,d0
  871. putc:
  872. putb2:    tst.b    TSR
  873.     bpl.s    putb2
  874.     move.b    d0,UDR
  875.     rts
  876.  
  877. crlf:    move.l    #crlfmsg,-(sp)
  878.     bsr    puts
  879.     addq    #4,sp
  880.     rts
  881.  
  882. puts:    movea.l    4(sp),a0
  883. .1:    move.b    (a0)+,d0
  884.     beq.s    .9
  885.     bsr    putc
  886.     bra.s    .1
  887. .9:    rts
  888.  
  889. crlfmsg: dc.b    13,10,0
  890.     .even
  891.   .endif ;VERBOSE
  892.  
  893. * page 
  894. *+
  895. * _do_rw - called to read/write no more than 128K to an even boundary
  896. *
  897. * Passed:    dev    $e(sp).W
  898. *        recno    $c(sp).W
  899. *        count    $a(sp).W
  900. *        buf    6(sp).L
  901. *        rw    4(sp).W        ; non-zero -> write
  902. *
  903. *-
  904.     .globl    _do_rw
  905. _do_rw:
  906.     move.w    d3,-(sp)        ; preserve d3
  907.  
  908. sasrw0:    move.w    _retries,retrycnt    ; setup retry counter
  909.  
  910.     move.w    6(sp),d3
  911.     btst    #2,d3            ; are retries disabled?
  912.     beq    sasrw1            ; no, act normally
  913.     move.w    #0,retrycnt        ; yes, so set retrycnt to zero
  914.  
  915. *
  916. * read sector(s),
  917. * delay .0005 to .001 seconds between driver calls
  918. *
  919. sasrw1:
  920.     move.l    lastrwtm,d0
  921. sasrw8:    cmp.l    _hz_200,d0        ; while (_hz_200 <= lastrwtm)
  922.     bcc    sasrw8            ;    just_wait;
  923.     move.l    _hz_200,d0        ; lastrwtm = _hz_200 + 1;
  924.     addq.l    #1,d0
  925.     move.l    d0,lastrwtm
  926.  
  927.     lea    2(sp),a1        ; frame pointer
  928.     moveq    #0,d0            ; coerce word to long, unsigned
  929.     move.w    $c(a1),d0        ; sect.L
  930.     move.w    4(a1),d3        ; rw
  931.  
  932.     btst    #3,d3            ; physical unit operation
  933.     beq    sasrw2            ; no, so do log->phys mapping
  934.  
  935.     move    $0e(a1),d2        ; get unit number
  936.     subq    #2,d2            ; subtract drive C offset
  937.     bra    sasrw3            ; and use that as the physical unit
  938.  
  939. sasrw2:    clr    d2            ; coerce byte to word
  940.     move.w    $e(a1),d1        ; get device
  941.     lea    pun,a2
  942.     move.b    0(a2,d1.w),d2        ; get physical unit number
  943. sasrw3:    move.w    d2,-(sp)        ; dev
  944.     move.l    6(a1),-(sp)        ; buf
  945.     move.w    $a(a1),-(sp)        ; count
  946.  
  947.     btst    #3,d3            ; physical operation?
  948.     bne    sasrw4            ; yes, so no offset
  949.  
  950.     asl.w    #2,d1            ; *4 to get index into long array
  951.     lea    start,a2
  952.     add.l    0(a2,d1.w),d0        ; adjust sector number
  953.  
  954. sasrw4:    move.l    d0,-(sp)        ; sect
  955.     btst    #0,d3            ; read or write?
  956.     bne    sasrw5            ; (write)
  957.     bsr    _hread            ; read sectors
  958.     bra    sasrw6
  959. sasrw5:    bsr    _hwrite            ; write sectors
  960. sasrw6:    add.w    #12,sp            ; (cleanup stack)
  961.     tst.l    d0            ; errors?
  962.     beq    sasrwr            ; no -- success
  963.     subq.w    #1,retrycnt        ; drop retry count and retry
  964.     bpl    sasrw1
  965.  
  966.     move    6(sp),d1        ; get r/w and flags word
  967.     move.l    #EREADF,d0        ; read error code
  968.     btst    #0,d1
  969.     beq    sasrw7
  970.     move.l    #EWRITF,d0        ; write error code
  971.  
  972. sasrw7:    btst    #2,d1            ; is this a "raw" operation?
  973.     bne    sasrwr            ; yes, so no critical error handler
  974.  
  975.     move.w    $10(sp),-(sp)        ; unit number
  976.     move.w    d0,-(sp)        ; error code (as a word, sic)
  977.     movea.l    etv_critic,a0
  978.     jsr    (a0)
  979.     addq    #4,sp
  980.     cmpi.l    #CRITRETRY,d0        ; is it the magic RETRY code?
  981.     beq    sasrw0
  982.  
  983. sasrwr:    move.w    (sp)+,d3        ; remember to restore d3
  984.     rts
  985.  
  986. *+
  987. * _sasi_mediach - see if hard disk media has changed (it never does)
  988. * Synopsis:    _sasi_mediach(dev)
  989. *        WORD dev;
  990. *
  991. * Returns:    0L
  992. *
  993. *-
  994.     .globl    _sasi_mediach
  995. _sasi_mediach:
  996.     clr.l    d0
  997.     rts
  998.  
  999.  
  1000. * page 
  1001. * ---------------- Low-level driver ----------------
  1002.  
  1003.  
  1004. *----- Hardware:
  1005. wdc        equ    $ffff8604
  1006. wdl        equ    $ffff8606
  1007. wdcwdl        equ    wdc        ; used for long writes
  1008. xwdl        equ    wdl-wdc        ; offset from wdc to wdl
  1009.  
  1010. dmahi        equ    $ffff8609
  1011. dmamid        equ    dmahi+2
  1012. dmalow        equ    dmamid+2
  1013. gpip        equ    $fffffa01
  1014.  
  1015.  
  1016. *----- Tunable:
  1017. ltimeout        equ    450000        ; long-timeout (3 S)
  1018. stimeout        equ    15000        ; short-timeout (100 mS)
  1019.  
  1020. *+
  1021. * LONG _qdone() - Wait for command byte handshake
  1022. * LONG _fdone() - Wait for operation complete
  1023. * Passed:    nothing
  1024. *
  1025. * Returns:    EQ: no timeout
  1026. *        MI: timeout condition
  1027. *
  1028. * Uses:        D0
  1029. *
  1030. * each pass through the loop takes 6.75 uS
  1031. *-
  1032.     .if    sermsg
  1033.  
  1034. _fdone:    move    d1,-(sp)
  1035.     move    #1,d1
  1036.     move.l    #ltimeout,tocount
  1037.     bra    qd1
  1038.  
  1039. _qdone:
  1040.     move    d1,-(sp)
  1041.     move    #0,d1
  1042.     move.l    #stimeout,tocount
  1043. qd1:    subq.l    #1,tocount        ; drop timeout count
  1044.     bmi    qdq            ; (i give up, return NE)
  1045.     btst    #5,gpip            ; interrupt?
  1046.     bne    qd1            ; (not yet)
  1047.  
  1048.     move    (sp)+,d1
  1049.     moveq    #0,d0            ; return EQ (no timeout)
  1050.     rts
  1051.  
  1052. qdq:    nop
  1053.  
  1054.     .if    1
  1055.  
  1056.     movem.l    d0-d3/a0-a4,-(sp)
  1057.     lea    stmsg,a4
  1058.     tst    d1
  1059.     beq    qdq1
  1060.     lea    ltmsg,a4
  1061. qdq1:    move.b    (a4)+,d0
  1062.     beq    qdq2
  1063.     move    d0,-(sp)
  1064.     move    #1,-(sp)
  1065.     move    #3,-(sp)
  1066.     trap    #13
  1067.     addq    #6,sp
  1068.     bra    qdq1
  1069.  
  1070. qdq2:    movem.l    (sp)+,d0-d3/a0-a4
  1071.  
  1072.     .endif
  1073.  
  1074.     move    (sp)+,d1
  1075.     moveq    #-1,d0
  1076.     rts
  1077.  
  1078. stmsg:    dc.b    'Short timeout',$0d,$0a,0
  1079. ltmsg:    dc.b    'Long timeout',$0d,$0a,0
  1080. drmsg:    dc.b    $0d,$0a,'Drive ',0
  1081.     even
  1082.  
  1083.     .endif
  1084.  
  1085.     .if    sermsg=0
  1086.  
  1087. _fdone:    move.l    #ltimeout,tocount
  1088.     bra    qd1
  1089.  
  1090. _qdone:
  1091.     move.l    #stimeout,tocount
  1092. qd1:    subq.l    #1,tocount        ; drop timeout count
  1093.     bmi    qdq            ; (i give up, return NE)
  1094.     btst    #5,gpip            ; interrupt?
  1095.     bne    qd1            ; (not yet)
  1096.  
  1097.     moveq    #0,d0            ; return EQ (no timeout)
  1098.     rts
  1099.  
  1100. qdq:    moveq    #-1,d0
  1101.     rts
  1102.  
  1103.     .endif
  1104.  
  1105. *+
  1106. * WORD _endcmd()
  1107. * Wait for end of SASI command
  1108. * Passed:    d0 value to be written to wdl
  1109. *
  1110. * Returns:    EQ: success (error code in D0.W)
  1111. *        MI: timeout
  1112. *        NE: failure (SASI error code in D0.W)
  1113. *
  1114. * Uses:        d0,d1
  1115. *-
  1116. _endcmd: move    d0,d1            ; preserve wdl value
  1117.  
  1118.     bsr    _fdone            ; wait for operation complete
  1119.     bmi    endce            ; (timed-out, so complain)
  1120.  
  1121.     move.w    d1,wdl
  1122.     nop
  1123.     move.w    wdc,d0            ; get the result
  1124.     and.w    #$00ff,d0        ; (clean it up), if non-zero should
  1125.  
  1126. endce:    rts                ;  do a ReadSense command to learn more
  1127.  
  1128. *-
  1129. * _hread(sectno, count, buf, dev)
  1130. * LONG sectno;         4(sp)
  1131. * WORD count;         8(sp)
  1132. * LONG buf;        $a(sp)    $b=high, $c=mid, $d=low
  1133. * WORD dev;        $e(sp)
  1134. *
  1135. * Returns:    -1 on timeout
  1136. *        0 on success
  1137. *        nonzero on error
  1138. *
  1139. *-
  1140.     .globl    _hread
  1141. _hread:
  1142.     movea.l    #wdc,a0            ; pointer to DMA chip
  1143.     st    flock            ; lock FIFO
  1144.  
  1145.     move    #$88,xwdl(a0)
  1146.     clr.l    d0
  1147.     move.w    $0e(sp),d0        ; get unit number
  1148.     lsl.w    #5,d0
  1149.     swap    d0
  1150.     ori.l    #$0008008a,d0        ; 08 wdc, 8a wdl
  1151.     move.l    d0,(a0) ; wdcwdl
  1152.  
  1153.     move.l    $a(sp),-(sp)        ; set DMA address
  1154.     bsr    _setdma
  1155.     addq    #4,sp
  1156.  
  1157.     bsr    _setss            ; set sector and size
  1158.     bmi    _hto
  1159.  
  1160.     move.w    #$190,xwdl(a0)
  1161.     nop
  1162.     move.w    #$90,xwdl(a0)
  1163.     nop
  1164.     move.w    8(sp),(a0) ;wdc        ; write sector count to DMA chip
  1165.     nop
  1166.     move.w    #$8a,xwdl(a0)
  1167.     nop
  1168.     move.l    #$00000000,(a0) ; wdcwdl; control byte  0 wdc 0 wdl
  1169.  
  1170.     move.w    #$8a,d0
  1171.     bsr    _endcmd
  1172.  
  1173. hrx:    bra    _hdone            ; cleanup after IRQ
  1174.  
  1175.  
  1176. *-
  1177. * _hwrite(sectno, count, buf, dev)
  1178. * LONG sectno;         4(sp)
  1179. * WORD count;         8(sp)
  1180. * LONG buf;        $a(sp)    $b=high, $c=mid, $d=low
  1181. * WORD dev;        $e(sp)
  1182. *
  1183. *-
  1184.     .globl    _hwrite
  1185. _hwrite:
  1186.     movea.l    #wdc,a0            ; pointer to DMA chip
  1187.     st    flock            ; lock FIFO
  1188.  
  1189.     move.l    $a(sp),-(sp)        ; set DMA address
  1190.     bsr    _setdma
  1191.     addq    #4,sp
  1192.  
  1193.     move.w    #$88,xwdl(a0)
  1194.     clr.l    d0
  1195.     move.w    $0e(sp),d0        ; get unit number
  1196.     lsl.w    #5,d0
  1197.     swap    d0
  1198.     ori.l    #$000a008a,d0        ; 0a wdc 8a wdl
  1199.     move.l    d0,(a0) ; wdcwdl
  1200.  
  1201.     bsr    _setss
  1202.     bmi    _hto
  1203.  
  1204.     move.w    #$90,xwdl(a0)
  1205.     nop
  1206.     move.w    #$190,xwdl(a0)
  1207.     nop
  1208.     move.w    8(sp),(a0) ;wdc        ; sector count for DMA chip's benefit
  1209.     nop
  1210.     move.w    #$18a,xwdl(a0)
  1211.     nop
  1212.     move.l    #$00000100,(a0) ; wdcwdl
  1213.  
  1214.     move.w    #$18a,d0
  1215.     bsr    _endcmd
  1216.  
  1217. hwx:    bra    _hdone            ; cleanup after IRQ
  1218.  
  1219.  
  1220. *+
  1221. * void _setdma(addr)
  1222. * LONG addr;
  1223. *-
  1224. _setdma:
  1225.     move.b    7(sp),dmalow
  1226.     move.b    6(sp),dmamid
  1227.     move.b    5(sp),dmahi
  1228.     rts
  1229.  
  1230. *+
  1231. * WORD _setss  -- set sector number and number of sectors
  1232. *-
  1233.  
  1234. _setss:    move.w    #$8a,xwdl(a0)
  1235.  
  1236.     bsr    _qdone            ; wait for controller to take command
  1237.     bmi    setsse
  1238.  
  1239.     move.b    9(sp),d0        ; construct sector#
  1240.     swap    d0
  1241.     move.w    #$008a,d0
  1242.     move.l    d0,(a0) ; wdcwdl    ; write MSB sector# + devno
  1243.     bsr    _qdone
  1244.     bmi    setsse
  1245.  
  1246.     move.b    10(sp),d0        ; write MidSB sector#
  1247.     swap    d0
  1248.     move.w    #$008a,d0
  1249.     move.l    d0,(a0) ; wdcwdl
  1250.     bsr    _qdone
  1251.     bmi    setsse
  1252.  
  1253.     move.b    11(sp),d0        ; write LSB sector#
  1254.     swap    d0
  1255.     move.w    #$008a,d0
  1256.     move.l    d0,(a0) ; wdcwdl
  1257.     bsr    _qdone
  1258.     bmi    setsse
  1259.  
  1260.     move.w    12(sp),d0        ; write sector count
  1261.     swap    d0
  1262.     move.w    #$008a,d0
  1263.     move.l    d0,(a0) ; wdcwdl
  1264.     bsr    _qdone
  1265.  
  1266. setsse:    rts
  1267.  
  1268. _hto:    moveq    #-1,d0        ; indicate timeout
  1269. _hdone:    move.w    #$80,wdl    ; Landon's code seems to presume we
  1270.     nop            ;  put this back to $80
  1271.     tst.w    wdc
  1272.     clr    flock        ; NOW, signal that we are done
  1273.     rts
  1274.  
  1275. isasi5:
  1276.   .if ospool
  1277.     bsr    pool_install    ; attempt to install more OS pool
  1278.   .endif
  1279.     move.l    d0,-(sp)    ; preserve the number of bytes we need
  1280.  
  1281.     tst.w    bootloaded    ; if bootloaded, then already in super mode
  1282.     bne    nboot1        ; (already there)
  1283.     move.l    savssp,-(sp)    ; become a mild mannered user process
  1284.     move.w    #$20,-(sp)    ; Super(savssp)
  1285.     trap    #1
  1286.     addq    #6,sp
  1287.  
  1288. nboot1:    move.l    (sp)+,d0    ; compute value for Ptermres() or Mshrink
  1289.     add.l    #((i_sasi1-i_sasi)+$0100),d0
  1290.  
  1291.     tst.w    bootloaded    ; exit to GEMDOS?
  1292.     beq    nboot2        ; (yes -- not boot loaded)
  1293.  
  1294. *
  1295. *  Return to TOS ROMs
  1296. *    - set default boot device to C:
  1297. *    - Print silly message
  1298. *    - Mshrink() memory that was alloc'd to us
  1299. *    - set magic# in D7 for TOS ROMs
  1300. *    - RTS back to ROMs
  1301. *
  1302.     move.l    d0,-(sp)    ; save D0
  1303.     pea    msg_loaded(pc)    ; print announcement
  1304.     move.w    #9,-(sp)
  1305.     trap    #1
  1306.     addq    #6,sp
  1307.     move.l    (sp)+,d0
  1308.  
  1309.     move.w    #2,_bootdev    ; set default boot device to C: (devno=2)
  1310.     move.l    d0,-(sp)
  1311.     move.l    baseaddr,-(sp)
  1312.     clr.w    -(sp)
  1313.     move.w    #$4a,-(sp)    ; Mshrink(...)
  1314.     trap    #1
  1315.     add.w    #12,sp        ; (cleanup stack)
  1316.  
  1317.  
  1318. exec_os        equ    $4fe
  1319.  
  1320. *+
  1321. *  Bring up the AES:
  1322. *    do autoexec;
  1323. *    construct an enviroment string;
  1324. *    create a basepage for the AES;
  1325. *    exec the AES.
  1326. *
  1327. *-
  1328. st_1:
  1329.     bsr    findpackages        ; find bootable RAM packages
  1330.     bsr    _auto            ; do auto-exec
  1331.  
  1332.     pea    orig_env        ; push address of enviroment string
  1333.     pea    nullenv(pc)        ; no arguments
  1334.     pea    nullenv(pc)        ; null shell name (in ROM, after all)
  1335.     move.w    #5,-(sp)        ; createPSP flavor of exec
  1336.     move.w    #$4b,-(sp)        ; exec function#
  1337.     trap    #1            ; get pointer to PSP
  1338.     add.w    #14,sp            ; (clean up cruft)
  1339.     move.l    d0,a0            ; a0 -> PSP
  1340.     move.l    exec_os,8(a0)        ; stuff saddr of GEM in PSP
  1341.  
  1342.     move.l    a0,-(sp)        ; push addr of PSP
  1343.     pea    nullenv(pc)        ; null filename
  1344.     move.w    #4,-(sp)        ; just-go
  1345.  
  1346. st_x:    move.w    #$4b,-(sp)        ; function = exec
  1347.     trap    #1            ; do it
  1348.     add.w    #14,sp            ; cleanup stack
  1349.  
  1350. *+
  1351. * When startup fails (or if the exec returns,
  1352. * which "cannot happen") fake a system reset:
  1353. *-
  1354.     move.l    4,a0            ; get RESET vector
  1355.     jmp    (a0)            ; and do it
  1356.  
  1357.  
  1358.  
  1359. *+
  1360. * Default enviroment string
  1361. *
  1362. *-
  1363. orig_env:
  1364.     dc.b    "PATH=",0        ; default pathname
  1365.     dc.b    "C:\\",0        ; is the boot device
  1366.     dc.b    0            ; terminate env string
  1367.  
  1368.  
  1369. gemname: dc.b    "GEM.PRG"        ; desktop name
  1370. nullenv: dc.b    0,0            ; null string (and enviroment)
  1371.     even
  1372.  
  1373.  
  1374. *+
  1375. *  Auto path for hard disks (C:)
  1376. *
  1377. *-
  1378. autopath:    dc.b    'C:\\AUTO\\'
  1379. autofile:    dc.b    '*.PRG',0
  1380.         dc.w    $1234,$5678,$9abc,$def0
  1381.     even
  1382.  
  1383.  
  1384. *+
  1385. * _auto - exec auto-startup files in the appropriate subdirectory
  1386. * _auto1 - exec (with filename args)
  1387. *
  1388. * Passed:    a0 -> full filespec (pathname)
  1389. *        a1 -> filename part of filespec
  1390. *
  1391. * Returns:    nothing
  1392. *
  1393. * Uses:        everything
  1394. *-
  1395.     .globl    _auto            ; for debugging
  1396. _auto:    lea    autopath(pc),a0        ; -> path
  1397.     lea    autofile(pc),a1        ; -> filename
  1398.  
  1399. _auto1:    move.l    (sp)+,autoret        ; copy return addr (used by execlr)
  1400.     move.l    sp,origstk        ; (save original stack)
  1401.     move.l    a0,pathname        ; setup filename/pathname ptrs
  1402.     move.l    a1,filename
  1403.  
  1404.     lea    nullenv(pc),a3        ; a0 -> \0\0
  1405.     move.l    a3,-(sp)        ; null enviroment
  1406.     move.l    a3,-(sp)        ; null command tail
  1407.     move.l    a3,-(sp)        ; null shell name
  1408.     move.w    #5,-(sp)        ; Create-PSP subfunction
  1409.     move.w    #$4b,-(sp)        ; exec function#
  1410.     trap    #1            ; do DOS call
  1411.     add.w    #16,sp
  1412.  
  1413.     move.l    d0,a0            ; a0 -> PSP
  1414.     move.l    #fauto,8(a0)        ; initial PC -> autoexec prog
  1415.  
  1416.     move.l    a3,-(sp)        ; null enviroment
  1417.     move.l    d0,-(sp)        ; -> PSP
  1418.     move.l    a3,-(sp)        ; null shell name
  1419.     move.w    #4,-(sp)        ; just-go
  1420.     move.w    #$4b,-(sp)        ; function = exec
  1421.     trap    #1            ; do it
  1422.     add.w    #16,sp            ; cleanup stack & goodbye
  1423. autoq:    move.l    autoret,-(sp)
  1424.     rts
  1425.  
  1426.  
  1427.  
  1428. *+
  1429. *  fauto - exec'd by _auto to do autostartup
  1430. *
  1431. *  Passed:    pathname -> path part of filespec
  1432. *        filename -> file part of filespec
  1433. *
  1434. *-
  1435. fauto:
  1436.     move.w    #2,-(sp)        ; Dsetdrv(2)
  1437.     move.w    #$e,-(sp)
  1438.     trap    #1
  1439.     addq    #4,sp
  1440.  
  1441.     clr.l    -(sp)            ; get into super mode
  1442.     move.w    #$20,-(sp)
  1443.     trap    #1
  1444.     addq    #6,sp            ; cleanup
  1445.     move.l    d0,a4            ; a4 -> saved super stack
  1446.  
  1447. *--- free up some memory:
  1448.     move.l    4(a7),a5        ; a5 -> base page
  1449.     lea    $100(a5),sp        ; sp -> new, safer addr
  1450.     move.l    #$100,-(sp)        ; keep $100 (just the basepage)
  1451.     move.l    a5,-(sp)        ; -> start of mem to keep
  1452.     clr.w    -(sp)            ; junk word
  1453.     move.w    #$4a,-(sp)        ; setblock(...)
  1454.     trap    #1
  1455.     addq    #6,sp
  1456.     tst.w    d0
  1457.     bne    au_dn            ; punt on error
  1458.  
  1459.     move.w    #$0007,-(sp)        ; find r/o+hidden+system files
  1460.     move.l    pathname,-(sp)        ; -> filename (on input)
  1461.     move.w    #$4e,-(sp)        ; searchFirst
  1462.  
  1463.     moveq    #8,d7            ; d7 = cleanup amount
  1464. au1:    pea    autodma            ; setup DTA (for search)
  1465.     move.w    #$1a,-(sp)
  1466.     trap    #1
  1467.     addq    #6,sp
  1468.  
  1469.     trap    #1            ; search first/search next
  1470.     add.w    d7,sp            ; cleanup stack
  1471.     tst.w    d0            ; test for match
  1472.     bne    au_dn            ; (no match -- quit)
  1473.  
  1474. *--- construct filename from path and the name we just found:
  1475.     move.l    pathname,a0        ; copy pathname
  1476.     move.l    filename,a2        ; a2 -> end+1 of pathname
  1477.     lea    autoname,a1
  1478. au3:    move.b    (a0)+,(a1)+        ; copy path part of name
  1479.     cmp.l    a0,a2            ; finished?
  1480.     bne    au3            ; (no)
  1481.     lea    autodma+30,a0        ; copy fname to end of pathname
  1482. au2:    move.b    (a0)+,(a1)+
  1483.     bne    au2
  1484.  
  1485.     pea    nullenv(pc)        ; null enviroment
  1486.     pea    nullenv(pc)        ; no command tail
  1487.     pea    autoname        ; -> file to exec
  1488.     clr.w    -(sp)            ; load-and-go
  1489.     move.w    #$4b,-(sp)        ; exec(...)
  1490.     trap    #1
  1491.     add.w    #16,sp
  1492.  
  1493.     moveq    #2,d7            ; reset cleanup amount
  1494.     move.w    #$4f,-(sp)        ; searchNext
  1495.     bra    au1
  1496.  
  1497. *+
  1498. * Search for a package, execute it.
  1499. *
  1500. *    +---------------+
  1501. *    |   $12123456    | base + 0, on a 512-byte boundary
  1502. *    |        |
  1503. *    +---------------+
  1504. *    |   -> base    | base + 4
  1505. *    |        |
  1506. *    +---------------+
  1507. *    |   (code)    | base + 8
  1508. *    /        /
  1509. *    /        /
  1510. *    |        |
  1511. *    +---------------+
  1512. *              base + 512
  1513. *
  1514. *    The entire 512-byte block should word-checksum to $5678.
  1515. *
  1516. *-
  1517. findpackages:
  1518.     move.l    phystop,a0        ; a0 -> top of memory
  1519. fpk_n:    sub.w    #512,a0            ; down 512 bytes
  1520.     cmp.l    #$400,a0        ; bottom of memory?
  1521.     beq    fpk_r            ; (yes -- punt)
  1522.     cmp.l    #$12123456,(a0)        ; check magic #
  1523.     bne    fpk_n            ; (no match, try next one)
  1524.     cmp.l    4(a0),a0        ; self-pointer?
  1525.     bne    fpk_n            ; (doesn't point to itself, retry)
  1526.  
  1527.     clr.w    d0            ; zero checksum reg
  1528.     move.l    a0,a1            ; a1 -> block to checksum
  1529.     move.w    #$ff,d1            ; do 256 words
  1530. fpk_1:    add.w    (a1)+,d0        ; sum a word
  1531.     dbra    d1,fpk_1        ;    ... until we're done
  1532.     cmp.w    #$5678,d0        ; magic number to exec()?
  1533.     bne    fpk_n            ; (no, retry)
  1534.     move.l    a0,-(sp)        ; save our precious package pointer
  1535.     jsr    8(a0)            ; call package's code
  1536.     move.l    (sp)+,a0        ; restore A0
  1537.     bra    fpk_n            ; (do more blocks)
  1538.  
  1539. fpk_r:    rts
  1540.  
  1541.  
  1542. *+
  1543. * The first GEMDOS process can never terminate.
  1544. * This is not a good feature.
  1545. * Kludge around it -- re-initialize the stack
  1546. * and return to the guy who called us to begin with.
  1547. *
  1548. *-
  1549. au_dn:    move.l    origstk,sp        ; restore original stack
  1550.     move.l    autoret,-(sp)        ; get return addr
  1551.     rts                ; just jump there ...
  1552.  
  1553.  
  1554. *--- "bss" for auto-exec:
  1555. autoret:    dc.l    0        ; -> _auto's caller (yeccch)
  1556. pathname:    dc.l    0        ; -> filespec's pathname
  1557. filename:    dc.l    0        ; -> filename part of path
  1558. origstk:    dc.l    0        ; =  original supervisor stack
  1559. autodma:    dcb.b    44,0        ; 44 bytes for directory search
  1560. autoname:    dcb.b    32,0        ; 32 bytes for path+filename
  1561.     even
  1562.  
  1563.  
  1564. *    move.b    #$100-$20,d7    ; return to TOS ROMs
  1565. *    rts
  1566.  
  1567. msg_loaded:
  1568.     dc.b    'Atari ACSI/SCSI Driver'
  1569.   .if !SCDMA
  1570.     dc.b    ' (ND)'
  1571.   .endif ;SCDMA
  1572.     dc.b    13,10
  1573.     dc.b    '  ('
  1574.     VERSION
  1575.     dc.b    ')',13,10
  1576.     dc.b    0
  1577.     even
  1578.  
  1579. *
  1580. *  Terminate and stay resident;
  1581. *  installed driver under GEMDOS.
  1582. *
  1583. nboot2:    
  1584.     move.l    d0,-(sp)    ; save D0
  1585.     pea    msg_loaded(pc)    ; print announcement
  1586.     move.w    #9,-(sp)
  1587.     trap    #1
  1588.     addq    #6,sp
  1589.     move.l    (sp)+,d0
  1590.  
  1591.     move.w    #0,-(sp)    ; exit code
  1592.     move.l    d0,-(sp)
  1593.     move.w    #$31,-(sp)    ; terminate and stay resident
  1594.     trap    #1        ; should never come back...
  1595.     illegal
  1596.  
  1597.  
  1598. * page 
  1599.  .if ospool
  1600. *+
  1601. *  Wire more pool into various ROM releases.
  1602. *
  1603. *    Passed:    nothing
  1604. *    Returns:    D0 = #bytes extra used
  1605. *
  1606. *-
  1607. pool_install:
  1608.     move.l    _sysbase,a3        ; a3 -> base of OS
  1609.  
  1610. * make sure we're in ROM,
  1611. * then get address of RAM location to patch:
  1612.  
  1613.     cmp.l    #$800000,a3        ; better be ROM
  1614.     blt    notrom
  1615.     lea    pool_tab(pc),a0        ; a0 -> table to match
  1616. pi_lp:    move.l    (a0)+,d1        ; d1 = date to match
  1617.     beq    badrom            ; (forget it, end of list)
  1618.     move.l    (a0)+,a2        ; a2 -> _root address for that date
  1619.     cmp.l    $18(a3),d1        ; match dates?
  1620.     bne    pi_lp            ; (no -- try again)
  1621.  
  1622.     lea    poolbuf+2,a0        ; a0 -> base of first buffer
  1623.     move.w    #numchunks-1,d0        ; d0 = count-1
  1624. pin_1:    lea    chunksiz(a0),a1        ; a1 -> next buffer
  1625.     move.l    a1,(a0)            ; buffer -> next one
  1626.     move.w    #chunkno,-2(a0)        ; install chunksiz
  1627.     move.l    a1,a0            ; a0 -> next buffer
  1628.     dbra    d0,pin_1        ; (do some more)
  1629.  
  1630.     sub.w    #chunksiz,a0        ; a0 -> last block
  1631.     move.l    chunkno*4(a2),(a0)    ; last block -> first in root
  1632.     move.l    #poolbuf+2,chunkno*4(a2) ; root -> first of ours
  1633.     move.l    #numchunks*chunksiz,d0    ; d0 = amount of BSS used **AKP**
  1634.     rts                ; return OK
  1635.  
  1636. *+
  1637. *  Print warning messages
  1638. *  about bogus versions of the
  1639. *  operating system.  Assume that
  1640. *  every OS past 1-May-1986 has the
  1641. *  pool fix installed.
  1642. *
  1643. *-
  1644. ok_date    =    %0000110010100001    ; 1-May-1986
  1645. notrom:    lea    m_notrom(pc),a0        ; ram-based system (5/29!)
  1646.     bra.s    bdrom1
  1647. badrom:    lea    m_badrom(pc),a0        ; illegal ROM system
  1648. bdrom1:    cmp.w    #ok_date,$1e(a3)    ; if ok_date <= os_dosdate(a3) 
  1649.     bcc    bdrom2            ; then don't print anything
  1650.  
  1651.     move.l    a0,-(sp)        ; print nasty message
  1652.     move.w    #9,-(sp)
  1653.     trap    #1
  1654.     addq    #6,sp
  1655.  
  1656. * print msg and wait for RETURN
  1657.     pea    keymsg(pc)
  1658.     move.w    #9,-(sp)
  1659.     trap    #1
  1660.     addq    #6,sp
  1661.  
  1662. bdrom3:    move.w    #2,-(sp)        ; wait for [RETURN]
  1663.     move.w    #2,-(sp)
  1664.     trap    #13
  1665.     addq    #4,sp
  1666.     cmp.w    #13,d0
  1667.     bne    bdrom3
  1668.  
  1669. bdrom2:    moveq    #0,d0            ; 0 extra bytes used
  1670.     rts
  1671.  
  1672. keymsg:    dc.b    'Hard disk driver not loaded; hit RETURN',13,10
  1673.     dc.b    'key to continue:',13,10
  1674.     dc.b    0
  1675.  
  1676. m_notrom:
  1677.     dc.b    '*** WARNING ***',13,10,7
  1678.     dc.b    'This hard disk driver may not work with',13,10,7
  1679.     dc.b    'a disk-based version of TOS; files on',13,10,7
  1680.     dc.b    'your hard disk may be damaged.',13,10,7
  1681.     dc.b    13,10,7
  1682.     dc.b    0
  1683.  
  1684. m_badrom:
  1685.     dc.b    '*** WARNING ***',13,10,7
  1686.     dc.b    'You are using an unofficial ROM release',13,10,7
  1687.     dc.b    'of the operating system.  This driver',13,10,7
  1688.     dc.b    'may not work correctly with it.  Files',13,10,7
  1689.     dc.b    'on your hard disk may be damaged.',13,10,7
  1690.     dc.b    13,10,7
  1691.     dc.b    0
  1692.     even
  1693.  
  1694.  
  1695. *+
  1696. *  Table of ROM release dates / _root addresses
  1697. *  update these for new ROM releases that need the patch.
  1698. *
  1699. *-
  1700. pool_tab:
  1701.     dc.l    $11201985,$56fa        ; USA and UK, 20-Nov-1985
  1702.     dc.l    $02061986,$56fa        ; Germany, 6-Feb-1986
  1703.     dc.l    $04241986,$56fa        ; France, 24-Apr-1986
  1704.     dc.l    0
  1705.  .endif
  1706.  
  1707. * page 
  1708.  
  1709. BPBLEN    equ    18
  1710.     .globl    _puns
  1711. _puns:
  1712. puns:    dc.w    0
  1713.  
  1714.     .globl    _pun
  1715. _pun:
  1716. pun:    dcb.b    maxunits,0
  1717.     .globl    _partstart
  1718. _partstart:
  1719. start:    dcb.l    maxunits,0
  1720. bpbs:    dcb.b    maxunits*18,0
  1721.  
  1722. lastrwtm:    dc.l    0        ; ``_hz_200 + 1'' at last _do_rw()
  1723. tocount:    dc.l    1        ; timeout counter
  1724. retrycnt:    dc.w    1        ; retry counter
  1725.     .globl    _retries
  1726. _retries:    dc.w    nretries    ; number of retries to do
  1727.  
  1728. o_init:        dc.l    1
  1729. o_bpb:        dc.l    1
  1730. o_rw:        dc.l    1
  1731. o_mediach:    dc.l    1
  1732.  
  1733.  .if ospool
  1734. poolbuf:    dc.w    0
  1735.  .endif
  1736.  
  1737. * page 
  1738. * ---------------- Installer ----------------
  1739. i_sasi1: nop
  1740.  
  1741.     tst.w    bootloaded        ; if boot-loaded, don't Super()
  1742.     bne    nboot3
  1743.     clr.l    -(sp)            ; it's a bird...
  1744.     move.w    #$20,-(sp)        ;    ... it's a plane ...
  1745.     trap    #1            ;      ... no, its:
  1746.     addq    #6,sp            ; SOOUPERUSER!
  1747.     move.l    d0,savssp        ; "Faster than a prefetched opcode..."
  1748.  
  1749. nboot3:    move    #maxunits-1,d1
  1750.     moveq    #-1,d0            ; a bad pun
  1751.     lea    pun,a0
  1752. i_sasi2: move.b    d0,(a0)+
  1753.     dbra    d1,i_sasi2
  1754.  
  1755.   .if VERBOSE
  1756.     andi.b    #($FF-$1E),IERA    ; turn off MFP serial interrupts
  1757.     andi.b    #($FF-$1E),IMRA    ; turn off MFP serial interrupts
  1758.  
  1759.     bsr    crlf
  1760.     move.l    #msg_loaded,-(sp)
  1761.     bsr    puts
  1762.     addq    #4,sp
  1763.   .endif ;VERBOSE
  1764.  
  1765.   .if SCSI
  1766.     bsr    resetSCSI    ; reset the SCSI bus
  1767.   .endif ;SCSI
  1768.  
  1769.     move    #2,clun            ; current logical unit number
  1770.     move.l    #4,cdbit        ; current drive bit
  1771.     move    #0,cpun            ; current physical unit number
  1772.     move    #0,installed        ; none installed yet
  1773.     move    #0,puns            ; no physical units found
  1774.  
  1775. i_sasi3:
  1776.     move.w    cpun,-(sp)        ; pread(sectno, cnt, buf, physunit)
  1777.     move.l    #pbuf,-(sp)
  1778.     move.w    #1,-(sp)        ; 1 sector
  1779.     move.l    #0,-(sp)        ; sectno = 0
  1780.     bsr    pread            ; try to read root sector
  1781.     adda    #12,sp
  1782.  
  1783.     tst.w    d0
  1784.     bne    i_sasi4            ; no controller/disk of that ACSI unit
  1785.  
  1786.     addq    #1,puns            ; found a physical unit
  1787.  
  1788.     bsr    ppu
  1789.  
  1790.     addq    #1,cpun
  1791.     cmpi    #8,cpun
  1792.     bne    i_sasi3
  1793.  
  1794. i_sasi4:
  1795.   .if SCSI
  1796. ; hack in a SCSI partition
  1797.     move.w    #1,puns
  1798.     move.w    #1,installed
  1799.     move.b    #$40,pun+2
  1800.     move.l    #2,start+(2*4)
  1801.     ori.l    #4,_drvbits
  1802.  
  1803.     movea.l    #bpbs+(2*BPBLEN),a2
  1804.     lea    thebpb,a1
  1805.     move    #BPBLEN-1,d0
  1806. .4:    move.b    (a1)+,(a2)+
  1807.     dbra    d0,.4
  1808.  
  1809.   .endif ;SCSI
  1810.     tst    puns            ; any drives found?
  1811.     beq    isase            ; nope, so just terminate
  1812.  
  1813.     clr.l    a5            ; zeropage ptr
  1814.     move.l    hdv_bpb(a5),o_bpb    ; save old vectors
  1815.     move.l    hdv_rw(a5),o_rw
  1816.     move.l    hdv_mediach(a5),o_mediach
  1817.  
  1818.     move.l    #hbpb,hdv_bpb(a5)    ; install our new ones
  1819.     move.l    #hrw,hdv_rw(a5)
  1820.     move.l    #hmediach,hdv_mediach(a5)
  1821.     move.l    #_puns,pun_ptr(a5)
  1822.  
  1823.     bra    isasi5        ; must get back into resident part
  1824.  
  1825. isase:    tst.w    bootloaded    ; if bootloaded, free block and punt
  1826.     bne    isaseb
  1827.     move.l    savssp,-(sp)    ; become a mild mannered user process
  1828.     move.w    #$20,-(sp)    ; Super(savssp)
  1829.     trap    #1
  1830.     addq    #6,sp
  1831.  
  1832.     move.w    #-1,-(sp)    ; exit code
  1833.     move.w    #$4C,-(sp)    ; terminate
  1834.     trap    #1        ; should never come back...
  1835.     illegal
  1836.  
  1837. *
  1838. *  Couldn't install driver, return to boot code
  1839. *
  1840. isaseb:    move.l    baseaddr,-(sp)    ; Mfree(baseaddr)
  1841.     move.w    #$49,-(sp)
  1842.     trap    #1
  1843.     addq.l    #6,sp
  1844.     move.b    #$100-$20,d7    ; return to TOS ROMs
  1845.     rts
  1846.  
  1847.  
  1848. * page 
  1849. *+
  1850. * pread(sectno, cnt, buf, physunit)
  1851. * LONG sectno;
  1852. * BYTE *buf; (word aligned)
  1853. * WORD cnt,physunit;
  1854. *
  1855. * Passed:    dev.w        $a(a0)    $e(sp)
  1856. *        &buf.l        $6(a0)    $a(sp)
  1857. *        cnt.w        $4(a0)    $8(sp)
  1858. *        sectno.l    $0(a0)    $4(sp)
  1859. *
  1860. * Returns:    -1 if we could not read it
  1861. *            (may not exist)
  1862. *-
  1863.     .globl    _pread
  1864. _pread:
  1865. pread:    move    _retries,retrycnt
  1866. pread1:    lea    4(sp),a0        ; frame pointer
  1867.     move.w    $a(a0),-(sp)        ; push physical unit number
  1868.     move.l    $6(a0),-(sp)        ; buffer address
  1869.     move.w    $4(a0),-(sp)        ; number to read
  1870.     move.l    (a0),-(sp)        ; sector number
  1871.     bsr    _hread
  1872.     adda    #12,sp
  1873.     tst    d0
  1874.     beq    pread9            ; no problems
  1875.     bmi    pread8            ; timeout, does not exist
  1876.     subq    #1,retrycnt        ; read error, try try again
  1877.     bpl    pread1
  1878. pread8:    moveq    #-1,d0
  1879.     rts
  1880.  
  1881. pread9:    move    #$8000,d0        ; delay for completion byte
  1882. preada:    subq    #1,d0
  1883.     bne    preada
  1884.     clr.l    d0            ; flag no errors
  1885.     rts
  1886.  
  1887. * page 
  1888. *+
  1889. * ppu
  1890. * Partition physical unit
  1891. *
  1892. *-
  1893. ppu:    move    #0,npart        ; number of partitions we have found
  1894.     movea.l    #pbuf+hd_siz,a0
  1895.     tst.l    (a0)+
  1896.     beq    ppu3            ; if 0, must not be valid
  1897.  
  1898.     moveq    #4-1,d1            ; maximum number of partitions/unit
  1899. ppu1:    movem.l    d1/a0,-(sp)
  1900.     tst.b    (a0)+            ; check the valid partition flag
  1901.     beq    ppu2            ; if 0, not a valid parition
  1902.  
  1903.     addq    #1,npart        ; number of partitions this unit
  1904.  
  1905.     cmpi.b    #'G',(a0)+        ; must find GEM as type
  1906.     bne    ppu2
  1907.     cmpi.b    #'E',(a0)+
  1908.     bne    ppu2
  1909.     cmpi.b    #'M',(a0)+
  1910.     bne    ppu2
  1911.  
  1912.     tst.l    4(a0)            ; is the size 0?
  1913.     beq    ppu2            ; then not a valid partition
  1914.  
  1915.     move.l    (a0),-(sp)        ; save start sector
  1916.  
  1917.     bsr    nxtdrv
  1918.  
  1919.     move.l    (sp)+,d1        ; recall start sector
  1920.  
  1921.     tst    d0            ; valid unit?
  1922.     bmi    ppu2
  1923.  
  1924.     movem.l    d1/a0-a1,-(sp)
  1925.  
  1926.     move.l    d1,-(sp)        ; getbpb(partition_start)
  1927.     bsr    getbpb            ; build bpb and put it in place
  1928.     addq    #4,sp
  1929.  
  1930.     movem.l    (sp)+,d1/a0-a1
  1931.  
  1932.     tst    d0
  1933.     bne    ppu2
  1934.  
  1935.     move.w    cpun,d0
  1936.     move.b    d0,(a0)
  1937.  
  1938.     move.l    d1,(a1)            ; start of partition
  1939.  
  1940.     addq    #1,clun
  1941.     addq    #1,installed        ; actually installed a hard disk
  1942.  
  1943. ppu2:    movem.l    (sp)+,d1/a0
  1944.     adda    #12,a0
  1945.     dbra    d1,ppu1
  1946.  
  1947.     tst    npart            ; did we find any?
  1948.     bne    ppu9
  1949.  
  1950. ppu3:    bsr    nxtdrv            ; no valid partitions found, assume
  1951.     move    cpun,d0            ;  whole thing is one big GEM disk
  1952.     move.b    d0,(a0)
  1953.     move.w    #0,(a1)            ; starts at 0
  1954.     lea    thebpb,a1
  1955.     move    #BPBLEN-1,d0
  1956. ppu4:    move.b    (a1)+,(a2)+
  1957.     dbra    d0,ppu4
  1958.  
  1959.     addq    #1,clun
  1960.     addq    #1,installed
  1961.  
  1962. ppu9:    rts
  1963.  
  1964. * page 
  1965. *+
  1966. * nxtdrv    (of clun, cdbit)
  1967. *    returns d0 = clun, or negative if error
  1968. *        a0 -> pun(clun)
  1969. *        a1 -> start(clun)
  1970. *        a2 -> bpbs(clun)
  1971. *-
  1972.  
  1973. nxtdrv:    cmpi    #maxunits,clun        ; have we already hit maximum?
  1974.     bge    nxtd9            ; yes, so signal error
  1975.  
  1976.     move.l    cdbit,d1        ; get the next bit to turn on
  1977.     move.l    _drvbits,d0        ; tell TOS we have the drive
  1978.     or.l    d1,d0
  1979.     move.l    d0,_drvbits
  1980.  
  1981.     asl.l    #1,d1
  1982.     move.l    d1,cdbit
  1983.     move    clun,d0
  1984.     lea    pun,a0
  1985.     adda    d0,a0
  1986.     lea    start,a1
  1987.     move    d0,d1
  1988.     asl    #2,d1            ; *4 for index into table of longs
  1989.     adda    d1,a1
  1990.     lea    bpbs,a2
  1991.     move    d0,d1
  1992.     mulu    #BPBLEN,d1
  1993.     adda    d1,a2
  1994.     rts
  1995.  
  1996. nxtd9:    moveq    #-1,d0
  1997.     rts
  1998.  
  1999. * page 
  2000. *+
  2001. * getbpb(sectorno)
  2002. * LONG sectorno;
  2003. *-
  2004.  
  2005. getbpb:    move.l    a2,-(sp)
  2006.  
  2007.     move.w    cpun,-(sp)        ; try to read this partition's
  2008.     move.l    #lbuf,-(sp)        ; boot sector
  2009.     move.w    #1,-(sp)        ; number of sectors
  2010.     move.l    16(sp),-(sp)        ; sectorno
  2011.     bsr    pread            ; pread(sectno, cnt, buf, physunit)
  2012.     adda    #12,sp
  2013.  
  2014.     movea.l    (sp)+,a2
  2015.  
  2016.     tst    d0            ; any trouble reading?
  2017.     bmi    getb9            ; bummer
  2018.  
  2019.     lea    lbuf,a3            ; pointer to boot sector
  2020.  
  2021.     move    #$0b,d0
  2022.     bsr    getlhw
  2023.     move    d0,(a2)+        ; =byt/sec
  2024.     move    d0,d1
  2025.  
  2026.     clr.w    d0
  2027.     move.b    $d(a3),d0
  2028.     move    d0,(a2)+        ; =sec/cluster
  2029.  
  2030.     mulu    d1,d0
  2031.     move    d0,(a2)+        ; =byt/cluster
  2032.  
  2033.     move    #$11,d0
  2034.     bsr    getlhw            ; number of directory entries
  2035.     mulu    #32,d0            ; size of each entry
  2036.     divu    d1,d0            ; number of sectors required
  2037.     move.l    d0,d1
  2038.     swap    d1
  2039.     tst    d1
  2040.     beq    getb1
  2041.     addq    #1,d0            ; round up
  2042. getb1:    move    d0,(a2)+        ; =rdlen
  2043.     move    d0,d2
  2044.  
  2045.     move    #$16,d0
  2046.     bsr    getlhw
  2047.     move    d0,(a2)+        ; =FATsize
  2048.     move    d0,d1
  2049.  
  2050.     move    #$e,d0
  2051.     bsr    getlhw            ; number of reserved sectors
  2052.     add    d1,d0
  2053.     move    d0,(a2)+        ; =2nd FAT start
  2054.  
  2055.     add    d1,d0            ; plus size of second fat
  2056.     add    d2,d0            ; plus rdlen
  2057.     move    d0,(a2)+        ; = data start
  2058.     move    d0,d2            ; save start of data
  2059.  
  2060.     move    #$13,d0
  2061.     bsr    getlhw            ; number of sectors on media
  2062.     sub    d2,d0            ; subtract number used by FATs,dir,boot
  2063.     clr.l    d1
  2064.     move    d0,d1
  2065.     clr    d0
  2066.     move.b    $d(a3),d0        ; number of sectors/cluster
  2067.     divu    d0,d1            ; rounding down
  2068.     move    d1,(a2)+        ; =number of clusters
  2069.     move    #1,(a2)            ; =flags, 16 bit fats
  2070.     clr.l    d0            ; no errors
  2071. getb9:    rts
  2072.  
  2073. *+
  2074. * WORD getlhw(d0=offset)
  2075. * returns word (low,high) from 0(D0,A3)
  2076. *-
  2077.  
  2078. getlhw:    move    d1,-(sp)        ; preserve d1
  2079.     move.b    1(a3,d0.w),d1
  2080.     lsl.w    #8,d1
  2081.     move.b    0(a3,d0.w),d1
  2082.     move    d1,d0
  2083.     move    (sp)+,d1
  2084.     rts
  2085.  
  2086. * page 
  2087.   .if    format
  2088. *+
  2089. *  _doformat - format hard disk
  2090. *
  2091. *    Synopsis:    LONG _doformat(dev, interlv)
  2092. *        WORD dev;            4(sp).W
  2093. *        WORD interlv;            6(sp).W
  2094. *
  2095. *-
  2096. acfmt:    dc.b    4    ; format command + devno (upper 3 bits)
  2097.     dc.b    0    ; (unused)
  2098.     dc.b    0    ; (unused) data pattern
  2099. ac_in:    dc.b    0,0    ; interleave factor MSB, LSB
  2100.     dc.b    0    ; reserved
  2101.     even
  2102.  
  2103.     .globl    _doformat
  2104. _doformat:
  2105.     move.w    4(sp),d0        ; set dev#
  2106.     lsl.b    #5,d0            ; up 5 bits, fill in 0s
  2107.     or.b    #4,d0            ; OR-in with FORMAT command
  2108.     move.b    d0,acfmt        ; stuff into command frame
  2109.     move.b    6(sp),ac_in        ; set interleave
  2110.     move.b    7(sp),ac_in+1
  2111.  
  2112.     lea    acfmt(pc),a0        ; pick up pointer to the command block
  2113.     clr.w    d0
  2114.     st    flock            ; lock FIFO
  2115.     move.w    #$88,wdl
  2116.     move.b    (a0)+,d0        ; get the command byte
  2117.     swap    d0
  2118.     move.w    #$8a,d0
  2119.     move.l    d0,wdc            ; byte wdc 8a wdl
  2120.  
  2121.     moveq    #(5-1),d1        ; write remaining 5 bytes of command
  2122. fmt1:    bsr    _qdone
  2123.     bmi    _hto
  2124.     move.b    (a0)+,d0        ; next byte of command
  2125.     swap    d0
  2126.     move.w    #$8a,d0
  2127.     move.l    d0,wdcwdl
  2128.     dbra    d1,fmt1
  2129.  
  2130. fmt2:    btst    #5,gpip            ; wait (forever) for completion
  2131.     bne    fmt2
  2132.     move.w    wdc,d0            ; get the status
  2133.     andi.w    #$00FF,d0        ; only low byte is significant
  2134.     bra    _hdone            ; cleanup after IRQ
  2135.  
  2136. * page 
  2137. *+
  2138. *  _mode_set - set hard disk format parameters
  2139. *
  2140. *    Synopsis:    LONG _mode_set(dev, parms)
  2141. *        WORD dev;            4(sp).W
  2142. *        char *parms;            6(sp).L
  2143. *
  2144. *-
  2145.     .globl    _mode_set
  2146. _mode_set:
  2147.     st    flock            ; lock FIFO
  2148.     move.l    6(sp),-(sp)        ; -> parameter block address
  2149.     bsr    _setdma            ; set DMA there
  2150.     addq    #4,sp
  2151.  
  2152. * write command and dev#
  2153.     move.w    #$88,wdl
  2154.     move.w    4(sp),d0        ; d0 = (dev << 5) << 16
  2155.     lsl.b    #5,d0
  2156.     swap    d0            ; in upper word
  2157.     or.l    #$0015008a,d0        ; write dev# + ModeSelect + FIFO bits
  2158.     move.l    d0,wdcwdl        ; mdsel+dev wdc 8a wdl (byte 0)
  2159.     bsr    _qdone
  2160.     bmi    wdx
  2161.  
  2162.     move.l    #$0000008a,wdcwdl    ; byte 1
  2163.     bsr    _qdone
  2164.     bmi    wdx
  2165.  
  2166.     move.l    #$0000008a,wdcwdl    ; byte 2
  2167.     bsr    _qdone
  2168.     bmi    wdx
  2169.  
  2170.     move.l    #$0000008a,wdcwdl    ; byte 3
  2171.     bsr    _qdone
  2172.     bmi    wdx
  2173.  
  2174.     move.l    #$0016008a,wdcwdl    ; 22 bytes of parameters (byte 4)
  2175.     bsr    _qdone
  2176.     bmi    wdx
  2177.  
  2178.     move.w    #$90,wdl        ; reset the DMA chip
  2179.     nop
  2180.     move.w    #$190,wdl
  2181.     nop
  2182.     move.w    #$01,wdc        ; 1 sector of DMA (actually less)
  2183.     nop
  2184.     move.w    #$18a,wdl
  2185.     nop
  2186.     move.l    #$00000100,wdcwdl    ; byte 5 (control byte)
  2187.     move.w    #$18a,d0        ; wdl value
  2188.     bsr    _endcmd            ; wait for command completion
  2189. wdx:    bra    _hdone
  2190.  
  2191.   .endif  ; format
  2192.  
  2193. * page 
  2194.   
  2195.   .if    mdsense
  2196. *+
  2197. *  _md_sense - get hard disk format parameters
  2198. *
  2199. *    Synopsis:    LONG _md_sense(dev, parms)
  2200. *        WORD dev;            4(sp).W
  2201. *        char *parms;            6(sp).L
  2202. *
  2203. *-
  2204.     .globl    _md_sense
  2205. _md_sense:
  2206.     st    flock            ; lock FIFO
  2207.     move.l    6(sp),-(sp)        ; -> parameter block address
  2208.     bsr    _setdma            ; set DMA there
  2209.     addq    #4,sp
  2210.  
  2211. * write command and dev#
  2212.     move.w    #$88,wdl
  2213.     move.w    4(sp),d0        ; d0 = (dev << 5) << 16
  2214.     lsl.b    #5,d0
  2215.     swap    d0            ; in upper word
  2216.     or.l    #$001a008a,d0        ; write dev# + ModeSense + FIFO bits
  2217.     move.l    d0,wdcwdl        ; mdsel+dev wdc 8a wdl (byte 0)
  2218.     bsr    _qdone
  2219.     bmi    wdx1
  2220.  
  2221.     move.l    #$0000008a,wdcwdl    ; byte 1
  2222.     bsr    _qdone
  2223.     bmi    wdx1
  2224.  
  2225.     move.l    #$0000008a,wdcwdl    ; byte 2
  2226.     bsr    _qdone
  2227.     bmi    wdx1
  2228.  
  2229.     move.l    #$0000008a,wdcwdl    ; byte 3
  2230.     bsr    _qdone
  2231.     bmi    wdx1
  2232.  
  2233.     move.l    #$0016008a,wdcwdl    ; 22 bytes of parameters (byte 4)
  2234.     bsr    _qdone
  2235.     bmi    wdx1
  2236.  
  2237.     move.w    #$190,wdl        ; reset the DMA chip
  2238.     nop
  2239.     move.w    #$90,wdl
  2240.     nop
  2241.     move.w    #$01,wdc        ; 1 sector of DMA (actually less)
  2242.     nop
  2243.     move.w    #$8a,wdl
  2244.     nop
  2245.     move.l    #0,wdcwdl        ; byte 5 (control byte)
  2246.     move.w    #$8a,d0            ; wdl value
  2247.     bsr    _endcmd            ; wait for command completion
  2248. wdx1:    bra    _hdone
  2249.  
  2250.   .endif  ; mdsense
  2251.  
  2252. * page 
  2253.   .if    sahdxc
  2254. *+
  2255. * LONG _dosahdxc( dev, addr ) BYTE *addr;
  2256. *    do a simple (no DMA) ahdx command
  2257. *-
  2258.     .globl    _dosahdxc
  2259. _dosahdxc: movea.l 6(sp),a0        ; pick up pointer to the command block
  2260.     clr.w    d0
  2261.     st    flock            ; lock FIFO
  2262.     move.w    #$88,wdl
  2263.     move    4(sp),d0        ; get the unit number
  2264.     lsl    #5,d0            ; shift it into place
  2265.     or.b    (a0)+,d0        ; or in the command byte
  2266.     swap    d0
  2267.     move.w    #$8a,d0
  2268.     move.l    d0,wdcwdl        ; send it to the controller
  2269.  
  2270.     moveq    #(5-1),d1        ; write remaining 5 bytes of command
  2271. dosac1:    bsr    _qdone
  2272.     bmi    _hto
  2273.     move.b    (a0)+,d0        ; next byte of command
  2274.     swap    d0
  2275.     move.w    #$8a,d0
  2276.     move.l    d0,wdcwdl
  2277.     dbra    d1,dosac1
  2278.  
  2279.     bsr    _fdone            ; wait for the command to complete
  2280.     bmi    _hto
  2281.  
  2282.     move.w    wdc,d0            ; get the status
  2283.     andi.w    #$00FF,d0        ; only low byte is significant
  2284.  
  2285.     bra    _hdone            ; cleanup after IRQ
  2286.  
  2287.   .endif    ; sahdxc
  2288.  
  2289. * page 
  2290.   .if s10mb
  2291. *+
  2292. * BPB for 10MB drive
  2293. *-
  2294. thebpb:    dc.w    512            ; #bytes/sector
  2295.     dc.w    2            ; #sectors/cluster
  2296.     dc.w    1024            ; #bytes/cluster
  2297.     dc.w    16            ; rdlen (256 root files) (in sectors)
  2298.     dc.w    41            ; FATsiz (10300 FAT entries) (sectors)
  2299.     dc.w    42            ; 2nd FAT start
  2300.     dc.w    99            ; data start (in sectors)
  2301.     dc.w    10300            ; #clusters (approximate here)
  2302.     dc.w    1            ; flags (16-bit FATs)
  2303.   .endif
  2304.  
  2305.   .if s11mb
  2306. *+
  2307. * BPB for 11MB Syquest partition
  2308. *-
  2309. thebpb:    dc.w    512            ; #bytes/sector
  2310.     dc.w    2            ; #sectors/cluster
  2311.     dc.w    1024            ; #bytes/cluster
  2312.     dc.w    17            ; rdlen (512 root files) (in sectors)
  2313.     dc.w    43            ; FATsiz (20736 FAT entries) (sectors)
  2314.     dc.w    44            ; 2nd FAT start
  2315.     dc.w    104            ; data start (in sectors)
  2316.     dc.w    10837            ; #clusters (approximate here)
  2317.     dc.w    1            ; flags (16-bit FATs)
  2318.   .endif
  2319.  
  2320.   .if s20mb
  2321. *+
  2322. * BPB for 20MB drive
  2323. *-
  2324. thebpb:    dc.w    512            ; #bytes/sector
  2325.     dc.w    2            ; #sectors/cluster
  2326.     dc.w    1024            ; #bytes/cluster
  2327.     dc.w    32            ; rdlen (512 root files) (in sectors)
  2328.     dc.w    81            ; FATsiz (20736 FAT entries) (sectors)
  2329.     dc.w    82            ; 2nd FAT start
  2330.     dc.w    195            ; data start (in sectors)
  2331.     dc.w    20710            ; #clusters (approximate here)
  2332.     dc.w    1            ; flags (16-bit FATs)
  2333.   .endif
  2334.  
  2335.   .if sahdxc
  2336.  
  2337. actur:    dc.b    0,0,0,0,0,0        ; atari command: test unit ready
  2338.  
  2339.   .endif ;sahdxc
  2340.  
  2341.  
  2342.     .even
  2343.  
  2344.     bss
  2345. savssp:    ds.l    1            ; (saved SSP)
  2346. clun:    ds.w    1
  2347. cpun:    ds.w    1
  2348. cdbit:    ds.l    1
  2349. npart:    ds.w    1            ; number of partitions found this pun
  2350. installed: ds.w    1            ; number hard disk partitions installed
  2351.  
  2352. hd_siz    equ    $1c2            ; offset into pbuf for partition info
  2353. pbuf:    ds.b    512
  2354. lbuf:    ds.b    512
  2355.  
  2356.     end
  2357.  -> filename part of path
  2358. origstk:    dc.l    0        ; =  original supervisor stack
  2359. autodma:    dcb.b    44,0        ; 44
  2360.